package top.v5it.japi.plus.extra.service;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import top.v5it.japi.plus.data.jdbc.mybatis.MybatisMapper;

import java.io.Serializable;
import java.util.Map;
import java.util.Optional;

/**
 * 统一分页服务层
 *
 * @author zhanpu
 * @date 2022/8/10
 */
public interface JapiQueryService {

    /**
     * 统一分页查询，统一采用{@link Map}格式传递参数
     *
     * @param params
     * @param name   spring上下文中beanName的前半部分，如service层 accountService 或者 repository 层 accountRepository 这里name取值为 account
     * @param <T>
     * @return
     */
    default <T> Page<T> query(Map<String, Object> params, String name) {
        final String beanName = name.concat("Repository");
        final MybatisMapper<T, Serializable> repository = SpringUtil.getBean(beanName);
        final PageRequest pageRequest = of(params);
        beforeQuery(params);
        final Page<T> page = repository.selectAllByMapCondition(params, pageRequest);
        return afterQuery(params, page);
    }

    /**
     * 之前调用
     *
     * @param params
     */
    default void beforeQuery(Map<String, Object> params) {
        //just a hook
    }

    /**
     * 之后调用
     *
     * @param params
     * @param resultSet
     * @param <T>
     * @return
     */
    default <T> Page<T> afterQuery(Map<String, Object> params, Page<T> resultSet) {
        //just a hook
        return resultSet;
    }

    /**
     * 构建分页信息
     *
     * @param params
     * @return
     */
    static PageRequest of(Map<String, Object> params) {
        return Optional
                .ofNullable(params)
                .filter(MapUtil::isNotEmpty)
                .filter(t -> t.containsKey("page"))
                .filter(t -> t.containsKey("size"))
                .map(t -> {
                            final Integer page = MapUtil.getInt(params, "page");
                            final Integer size = MapUtil.getInt(params, "size");
                            final String sort = MapUtil.getStr(params, "sort");
                            final String properties = MapUtil.getStr(params, "properties");
                            final String[] arr = StrUtil.splitToArray(properties, ',');

                            return StrUtil.isEmpty(sort)
                                    ? PageRequest.of(page, size)
                                    : PageRequest.of(page, size, Sort.Direction.fromString(sort), arr);
                        }
                )
                .orElse(PageRequest.of(0, 10));
    }

}
